/**
 * 
 */
package com.netscenery.yang.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import javax.xml.xpath.*;


import org.jdom2.Attribute;
import org.jdom2.Element;
import org.jdom2.Namespace;


import com.netscenery.util.ErrTag;
import com.netscenery.util.Field;
import com.netscenery.util.ILinkData;
import com.netscenery.util.Link;
import com.netscenery.util.QName;
import com.netscenery.util.XMLTag;
import com.netscenery.yang.YangKeyword;
import com.netscenery.yang.YangStatement;
import com.netscenery.yang.designer.LeafFieldMap;
import com.netscenery.yang.designer.ListFieldMap;
import com.netscenery.yang.designer.MapInfo;
import com.netscenery.yang.designer.MethodInfo;
import com.netscenery.yang.designer.Parameter;
import com.netscenery.yang.model.YangList.OrderBy;
import com.netscenery.yang.parser.YangParserException;

/**
 * @author llly
 *
 */
public abstract class Node extends DataDefElement implements ILinkData {
	protected DataDefEntity sons;
	protected boolean isUseDefaultConfig = true;
	protected boolean isConfig = true;
	private ArrayList<Typedef> typedefs;
	private ArrayList<Grouping> groupings;
	private ArrayList<Must> musts;
	
	public Node(Env env,String nodeName) throws ModelException{
		super(env,nodeName);
		if (null == env){
			return;
		}
		if (null == env.getParent()){
			return;
		}
		env.setCurNode(this);
		//�Ƕ���ڵ�
		if (env.getParent() instanceof Node){
			this.isConfig = ((Node)(env.getParent())).isConfig();
		}
		

		sons = new DataDefEntity(newSubEnv());
	}
	
	public Node (Env env, QName qname){
		super(env,qname);
		if (null == env){
			return;
		}
		if (null == env.getParent()){
			return;
		}
		env.setCurNode(this);
		//�Ƕ���ڵ�
		if (env.getParent() instanceof MainModule){
			
		}
		//�Ƕ���ڵ�
		else if (env.getParent() instanceof SubModule){
			
		}
		//���ӽڵ�
		else {
			
			this.isConfig = ((Node)(env.getParent())).isConfig();
		}
		sons = new DataDefEntity(newSubEnv());
	}
	
	
	public boolean isUseDefaultConfig() {
		return isUseDefaultConfig;
	}

	public String getPrefix() {
		return prefix;
	}


	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}


	
	public abstract boolean isMandatory();
	


	public DataDefEntity getSons() {
		return sons;
	}

	public void setSons(DataDefEntity sons) {
		this.sons = sons;
	}

	public DataDefElement createSon(String type, String name) throws ModelException{
		if ((this instanceof Leaf)
				|| (this instanceof LeafList)
				|| (this instanceof Anyxml)){
			return null;
		}
		return sons.createDataDef(type, name);		
	}
	public Validator addSon(DataDefElement child){
		return addSon(child, true);
	}
	public Validator addSon(DataDefElement child,boolean isNeedCheck){
		Validator validator = new Validator();
		if (null == child){
			validator.setIsValid(false);
			validator.addMsg(new Message(this,ErrTag.ERROR,ErrorCode.COMMON_ERROR));
			return validator;
		}
		if (isNeedCheck){
			if ((this instanceof Leaf)
					|| (this instanceof LeafList)
					|| this instanceof Anyxml){
				validator.setIsValid(false);
				StringBuffer message=new StringBuffer();
				if (this instanceof Leaf){
					message.append("leaf ");
				}
				else if (this instanceof LeafList) {
					message.append("leaf-list");
				}
				else if (this instanceof Anyxml) {
					message.append("anyxml");
				}
				
				message.append(" MUST not has any son.");
				validator.addMsg(new Message(this,ErrTag.ERROR,message.toString()));
				return validator;
			}
			
			DataDefElement[] sNodes = sons.searchDuplicateDef(child,0,this.getSonsNumber());
			if (null != sNodes){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"duplicate data definition.The data definition[path:"
						+sNodes[0].getPath()+"] is duplicate with the data definition[path:"
						+ sNodes[1].getPath() + "] that is already defined previously."));
				return validator;
			}
			//choice锟斤拷锟酵的节碉拷只锟斤拷锟斤拷锟絚ase锟斤拷锟酵碉拷锟接节碉拷
			if ((this instanceof Choice)
					&& !(child instanceof Case)){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"only node with case type can be accecpted as son node of son with choice type."));
				return validator;
			}
			
			if ((child instanceof Case)
					&& !(this instanceof Choice)){
				validator.setIsValid(false);
				validator.addMsg(new Message(this,ErrTag.ERROR,"node with case type can only be accecpted as son node of son with choice type."));
				return validator;
			}
		}

		
		if (null == sons){
			sons = new DataDefEntity(newSubEnv());
		}
		if (!sons.addDataDef(child)){
			validator.setIsValid(false);
			validator.addMsg(new Message(this,ErrTag.ERROR,ErrorCode.COMMON_ERROR));
			return validator;
		}
		child.setParent(this);
		return validator;
	}
	public int getSonsNumber(){
		if (null == sons){
			return 0;
		}
		
		return sons.getDataDefsNumber();
	}
	public DataDefElement getSon(int index){
		if (null == sons){
			return null;
		}
		
		return sons.getDataDef(index);
	}
	public DataDefElement getSon(String type,String name){
		if (null == type){
			return null;
		}
		if (null == name){
			return null;
		}
		
		if (type.equals("node")){
			return getNodeSon(name);
		}
		else {
			return getUsesSon(name);
		}
	}
	
	public Node getNodeSon(String name){
		if (null == name){
			return null;
		}
		
		if (null == sons){
			return null;
		}
		return sons.getNode(name);
		
	}
	public Uses getUsesSon(String name){
		if (null == name){
			return null;
		}
		
		if (null == sons){
			return null;
		}
		return sons.getUses(name);
		
	}	
	/**
	 * 获取真正的子节点，如逻辑子节点为uses，则需要把uses展开
	 * 如逻辑子节点为choice，则需要把choice下所有case下的节点
	 * 作为真正的子节点
	 * @return
	 */
	public ArrayList<Node> getDataSons(){
		if (null == sons){
			return null;
		}
		return sons.getDataNodes();
		
	}
	/**
	 * 获取从from到to index范围内的直接子节点对应的实际子节点
	 * 包含from指向的节点，不包含to指向的节点
	 * @param from
	 * @param to
	 * @return
	 */
	public ArrayList<Node> getDataSons(int from, int to){
		if (null == sons){
			return null;
		}
		return sons.getDataNodes(from, to);
		
	}
	public ArrayList<Node> getDataSons(String name){
		return getDataSons(name,0,getSonsNumber());
	}
	
	public ArrayList<Node> getDataSons(String name, int from, int to){
		if (null == sons){
			return null;
		}
		return sons.getDataNodes(name, from, to);
	}
	
	public Node getDataSon(String name){
		if (null == sons){
			return null;
		}
		return sons.getDataNode(name);
	}
	
	
	/**
	 * 获取模型树的子节点，如模型上的子节点为uses，则需要把uses展开
	 * 
	 * @return
	 */
	public ArrayList<Node> getSchemaSons(){
		int size = getSonsNumber();
		if (0 == size){
			return null;
		}
		return getSchemaSons(0,size);
		
	}
	/**
	 * 获取从from到to index范围内的直接子节点对应的模型子节点
	 * 包含from指向的节点，不包含to指向的节点
	 * @param from
	 * @param to
	 * @return
	 */
	public ArrayList<Node> getSchemaSons(int from, int to){
		if (null == sons){
			return null;
		}
		return sons.getSchemaNodes();
	}
	public ArrayList<Node> getSchemaSons(String name){
		return getSchemaSons(name,0,getSonsNumber());
	}
	
	public ArrayList<Node> getSchemaSons(String name, int from, int to){
		if (null == sons){
			return null;
		}
		return sons.getSchemaNodes(name,from,to);
	}
	
	public Node getSchemaSon(String name){
		if (null == sons){
			return null;
		}
		return sons.getSchemaNode(name);
	}
	public DataDefElement removeSon(int index){
		if (null == sons){
			return null;
		}
		
		return sons.removeDataDef(index);
	}
	
	public Node removeSonNode(String name){
		if (null == name){
			return null;
		}
		
		if (null == sons){
			return null;
		}
		
		return sons.removeNode(name);
	}
	public Uses removeSonUses(String name){
		if (null == name){
			return null;
		}
		
		if (null == sons){
			return null;
		}
		
		return sons.removeUses(name);
	}	
	public boolean moveSon(DataDefElement src,DataDefElement dst){
		if (null == sons){
			return false;
		}
		return sons.moveDataDef(src, dst);
	}
	
	public boolean moveSon(int srcIndex,int dstIndex){
		if (null == sons){
			return false;
		}
		return sons.moveDataDef(srcIndex, dstIndex);
	}
	public boolean moveSon(String srcType,String srcName,String dstType,String dstName){
		if (null == srcType){
			return false;
		}
		if (null == srcName){
			return false;
		}
		if (null == dstType){
			return false;
		}
		if (null == dstName){
			return false;
		}
		DataDefElement srcNode = getSon(srcType,srcName);
		DataDefElement dstNode = getSon(dstType,dstName);
		if (null == srcNode){
			return false;
		}
		return moveSon(srcNode, dstNode);
	}
	public Must createMust(Env env, String condition) throws ModelException{
		return new Must(env,condition);
	}
	public boolean addMust(Must must){
		if (null == must){
			return false;
		}
		if (null != getMust(must.getName())){
			return false;
		}
		if (null == musts){
			musts = new ArrayList<Must>(1);
		}
		return musts.add(must);
	}
	
	public Must getMust(int index){
		if (null == musts){
			return null;
		}
		return musts.get(index);
	}
	public Must getMust(String condition){
		if (null == musts){
			return null;
		}
		
		int size = musts.size();
		for (int i = 0; i< size;i++){
			Must must = musts.get(i);
			if (null != must){
				if (must.getName().equals(condition)){
					return must;
				}
			}
		}
		return null;
	}
	
	public Must removeMust(int index){
		if (null == musts){
			return null;
		}
		return musts.remove(index);
	}
	
	public Must removeMust(String condition){
		if (null == musts){
			return null;
		}
		
		int size = musts.size();
		for (int i = 0; i< size;i++){
			Must must = musts.get(i);
			if (null != must){
				if (must.getName().equals(condition)){
					return musts.remove(i);
				}
			}
		}
		return null;
	}
	
	public int getMustsNumber(){
		if (null == musts){
			return 0;
		}
		
		return musts.size();
	}
	/**
	 * �����ƴ���һ��typedef
	 * @param name
	 * @return
	 * @see com.netscenery.model.Typedef
	 */
	public Typedef createTypedef(String name){
		if (null == name){
			return null;
		}
		
		return new Typedef(newSubEnv(),name);
	}
	/**
	 * ���һ��typedef
	 * @param def
	 * @return
	 * @see com.netscenery.model.Typedef
	 */
	public boolean addTypedef(Typedef def){
		if(null == def){
			return false;
		}
		
		if (null == this.typedefs){
			this.typedefs = new ArrayList<Typedef>(1);
		}
		if(null != getTypedef(def.getName())){
			return false;
		}
		
		if (null != env.getDerivedType(def.getName())){
			return false;
		}
		this.typedefs.add(def);
		Env env = this.getEnv();
		env.addDerivedType(def);
		return true;
	}
	/**
	 * �����Ż�ȡtypedef
	 * @param index
	 * @return
	 * @see com.netscenery.model.Typedef
	 */
	public Typedef getTypedef(int index){
		if (null == this.typedefs){
			return null;
		}
		if (index >= this.typedefs.size()){
			return null;
		}
		return this.typedefs.get(index);
	}
	/**
	 * ���typedef��ƻ�ȡtypedef
	 * @param defName
	 * @return
	 * @see com.netscenery.model.Typedef
	 */
	public Typedef getTypedef(String defName){
		if (null == this.typedefs){
			return null;
		}
		int size = typedefs.size();
		if (size <= 0){
			return null;
		}
		
		for (int i = 0; i < size; i++){
			Typedef def = this.typedefs.get(i);
			if (null != def){
				if (def.getName().equals(defName)){
					return def;
				}
			}
		}
		return null;
	}
	/**
	 * ������ɾ��typedef
	 * @param index
	 * @return
	 * @see com.netscenery.model.Typedef
	 */
	public Typedef removeTypedef(int index){
		if (null == this.typedefs){
			return null;
		}
		if (index >= this.typedefs.size()){
			return null;
		}
		Typedef def = getTypedef(index);
		if (null == def){
			return null;
		}
		env.removeDataDef(getTypedef(index).name);
		return this.typedefs.remove(index);
	}
	/**
	 * ������ɾ��typedef
	 * @param defName
	 * @return
	 */
	public Typedef removeTypedef(String defName){
		if (null == this.typedefs){
			return null;
		}
		int size = typedefs.size();
		if (size <= 0){
			return null;
		}
		
		for (int i = 0; i < size; i++){
			Typedef def = this.typedefs.get(i);
			if (null != def){
				if (def.getName().equals(defName)){
					env.removeDerivedType(def.getName());
					return typedefs.remove(i);
				}
			}
		}
		return null;
	}
	/**
	 * ��ȡtypedef�ĸ���
	 * @return
	 */
	public int getTypedefsNumber(){
		if (null == this.typedefs){
			return 0;
		}
		return this.typedefs.size();
	}

	/**
	 * ��ȡgrouping����Ŀ
	 * @return
	 * @see com.netscenery.model.Grouping
	 */
	public int getGroupingsNumber(){
		if (null == this.groupings){
			return 0;
		}
		return this.groupings.size();
	}
	/**
	 * ���ָ������ƴ���grouping
	 * @param name
	 * @return
	 * @throws ModelException 
	 * @see com.netscenery.model.Grouping
	 */
	public Grouping createGrouping(String name) throws ModelException{
		if (null == name){
			return null;
		}
		
		return new Grouping(newSubEnv(),name);
	}
	/**
	 * ���һ��grouping
	 * @param n
	 * @return
	 * @see com.netscenery.model.Grouping
	 */
	public boolean addGrouping(Grouping n){
		if(null == n){
			return false;
		}
		
		if (null == this.groupings){
			this.groupings = new ArrayList<Grouping>(1);
		}
		if (null != this.getGrouping(n.getName())){
			return false;
		}
		
		if(null != env.getGrouping(n.getName())){
			return false;
		}
		if (!this.groupings.add(n)){
			return false;
		}
		
		if (!env.addGrouping(n)){
			removeGrouping(n.getName());
			return false;
		}
		return true;
		

	}
	/**
	 * �����Ż�ȡGrouping
	 * @param index
	 * @return
	 * @see com.netscenery.model.Grouping
	 */
	public Grouping getGrouping(int index){
		if (null == this.groupings){
			return null;
		}
		if (index >= this.groupings.size()){
			return null;
		}
		return this.groupings.get(index);
	}
	/**
	 * �����ƻ�ȡGrouping
	 * @param name
	 * @return
	 * @see com.netscenery.model.Grouping
	 */
	public Grouping getGrouping(String name){
		if (null == this.groupings){
			return null;
		}
		int size = groupings.size();
		if (size <= 0){
			return null;
		}
		
		for (int i = 0; i < size; i++){
			Grouping n = this.groupings.get(i);
			if (null != n){
				if (n.getName().equals(name)){
					return n;
				}
			}
		}
		return null;
	}
	/**
	 * ������ɾ��Grouping
	 * @param index
	 * @return Grouping
	 * @see com.netscenery.model.Grouping
	 */
	public Grouping removeGrouping(int index){
		if (null == this.groupings){
			return null;
		}
		if (index >= this.groupings.size()){
			return null;
		}
		Grouping g = groupings.get(index);
		if (null != g){
			env.removeGrouping(g.getName());
		}
		return this.groupings.remove(index);
	}
	/**
	 * ������ɾ��Grouping
	 * @param name
	 * @return Grouping
	 * @see com.netscenery.model.Grouping
	 */
	public Grouping removeGrouping(String name){
		if (null == this.groupings){
			return null;
		}
		int size = groupings.size();
		if (size <= 0){
			return null;
		}
		
		
		for (int i = 0; i < size; i++){
			Grouping n = this.groupings.get(i);
			if (null != n){
				if (n.getName().equals(name)){
					env.removeGrouping(n.getName());
					return groupings.remove(i);
				}
			}
		}
		return null;
	}


	/**
	 * 一个节点只有其祖先全部是模块或者子模块的子节点和后代节点时才
	 * 可能有绝对路径，否则只可能有descent类型的路径
	 * @return
	 */
	public String getPath(){
		return getPathByPrefix(null);
	}
	
	public String getPathByPrefix(String prefix){

		StringBuffer sb = new StringBuffer();
		Stack<String> s = new Stack<String>();
		Node node = this;
		
	
		boolean isAbsoultePath = true;
		//当前grouping不为空，则代表此节点为grouping中的节点
		//此时不应该具有绝对路径
		if(node.getEnv().getCurGrouping() != null){
			isAbsoultePath = false;
		}
		while(node != null){
			String qName= node.getName();
			if (null != prefix){
				qName = prefix + ":"+node.getName();
			}
			s.push(qName);
			DataDefElement data = node.getParent();
			if (null == data){
				//uses的情况
				if (node.getEnv().getParent() instanceof Node){
					node = (Node) node.getEnv().getParent();
				}
				else {
					break;	
				}
				
			}
			else {
				
				node = (Node) data;
			}
			
		}
		if (isAbsoultePath){
			sb.append("/" + s.pop());
		}
		else {
			sb.append(s.pop());
		}
		while(!s.isEmpty()){
			sb.append("/" + s.pop());
		}
		
		return sb.toString();
	}	
	public String getQualifiedPath(){
		StringBuffer sb = new StringBuffer();
		Stack<String> s = new Stack<String>();
		Node node = this;
		
	
		boolean isAbsoultePath = true;
		//当前grouping不为空，则代表此节点为grouping中的节点
		//此时不应该具有绝对路径
		if(node.getEnv().getCurGrouping() != null){
			isAbsoultePath = false;
		}
		while(node != null){
			
			s.push(node.getQName().toString());
			DataDefElement data = node.getParent();
			if (null == data){
				//uses的情况
				if (node.getEnv().getParent() instanceof Node){
					node = (Node) node.getEnv().getParent();
				}
				else {
					break;	
				}
			}
			else {
				node = (Node) data;
			}
			
		}
		if (isAbsoultePath){
			sb.append("/" + s.pop());
		}
		else {
			sb.append(s.pop());
		}
		while(!s.isEmpty()){
			sb.append("/" + s.pop());
		}
		
		return sb.toString();
	}
	/**
	 * ��ȡ�ڵ����ڵ���������list��key�������ϵ�����list��ʼ���У�
	 * ���������ڵ�
	 * @return
	 */
	public Stack<Node> getAncestorListsKeys(){
		Stack<Node> keys = new Stack<Node>();
		DataDefElement node = this.getParent();
		while(node != null){
			if(node instanceof YangList){
				YangList list = (YangList)node;
				int keysSize = list.getKeyFieldsNumber();
				for(int i = keysSize -1; i >= 0; i--){
					Node key = list.getKeyNode(i);
					if (null != key){
						keys.push(key);
					}
				}
			}
			node = node.getParent();
		}
		
		return keys;
	}
	
	
	/**
	 * judge this node whether is in list
	 * @return
	 */
	public boolean isInList(){
		DataDefElement node = this.getParent();
		while(node != null){
			if(node instanceof YangList){
				return true;
			}
			node = node.getParent();
		}
		
		return false;
	}
	
	public boolean hasLeafSon(){
		int size = this.getSonsNumber();
		if(0 == size){
			return false;
		}
		
		for (int i = 0; i < size;i++){
			DataDefElement n = getSon(i);
			if (null != n){
				if ((n instanceof Leaf)
						|| (n instanceof LeafList)){
					return true;
				}
			}
		}
		return false;
	}
	
	/**
	 * @return the isConfig
	 */
	public boolean isConfig() {
		return isConfig;
	}

	/**
	 * @param isConfig the isConfig to set
	 */
	public void setConfig(boolean isConfig) {
		this.isConfig = isConfig;
		if (true == isUseDefaultConfig){
			isUseDefaultConfig = false;
		}
	}
	


	

	/**
	 * �ڱ��ڵ��µ��ӽڵ��в����ظ��Ľڵ�,i��ʾ������Χ���ĸ��ӽڵ�
	 * @param node
	 * @param i

	 * @return
	 */

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#validate()
	 */
	@Override
	public Validator validate() {
		Validator v = new Validator();
		if (!checkName(this.getName())){
			v.setIsValid(false);
			v.addMsg(new Message(this,ErrTag.ERROR,ErrorCode.COMMON_INVALIDNAME));
		}
		
		if (null != sons && 0 != getSonsNumber()){
			v.copy(sons.validate());
		}
		Validator sv = super.validate();
		v.copy(sv);
		return v;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYang()
	 */
	@Override
	public YangStatement toYang() {
		YangStatement statement = null;
		String statementName = null;
		if (this instanceof Container){
			
			statementName = YangStatement.YANG_STATEMENT_CONTAINER;
		}
		else if (this instanceof Case){
			statementName = YangStatement.YANG_STATEMENT_CASE;
		}
		else if (this instanceof Choice){
			statementName = YangStatement.YANG_STATEMENT_CHOICE;
		}
		else if (this instanceof Leaf){
			statementName = YangStatement.YANG_STATEMENT_LEAF;
		}
		else if (this instanceof LeafList){
			statementName = YangStatement.YANG_STATEMENT_LEAFLIST;
		}
		else if (this instanceof YangList){
			statementName = YangStatement.YANG_STATEMENT_LIST;
		}
		else if (this instanceof Anyxml){
			statementName = YangStatement.YANG_STATEMENT_ANYXML;
		}
		else {
			return null;
		}
		statement = new YangStatement(statementName,this.name);
		
		if (!isNullString(this.when)){
			YangStatement when = new YangStatement(YangKeyword.WHEN.getKeyword(),this.when);
			statement.addChild(when);
		}
		
		//ͨ�ò���
		if (null != this.if_features){
			int size = this.getIf_featuresNumber();
			
			for (int i = 0; i < size; i++){
				String feature = this.getIf_feature(i);
				if (null != feature){
					YangStatement  featureState = 
							new YangStatement(
									YangStatement.YANG_STATEMENT_IFFEATURE
							        ,feature);
					statement.addChild(featureState);
				}
			}
			
		}
		if (0 != this.getMustsNumber()){
			int size = this.getMustsNumber();
			for (int i = 0; i < size; i++){
				Must must = getMust(i);
				if (null != must){
					YangStatement mustStatement = must.writeYang();
					if(null != mustStatement){
						statement.addChild(mustStatement);
					}
					
				}
			}
		}
		if (null != getDescription()){
			YangStatement descr = new YangStatement(YangStatement.YANG_STATEMENT_DESCRIPTION,getDescription());
			statement.addChild(descr);
		}
		if (null != getReference()){
			YangStatement ref = new YangStatement(YangStatement.YANG_STATEMENT_REFERENCE,this.getReference());
			statement.addChild(ref);
		}
		
		if (Status.CURRENT != getStatus()){
			YangStatement status = new YangStatement(YangStatement.YANG_STATEMENT_STATUS,this.getStatus().getStatus());
			statement.addChild(status);
		}
		
		if (null != groupings){
			int gSize = getGroupingsNumber();
			for (int i = 0; i < gSize; i++){
				Grouping grp = getGrouping(i);
				if (null != grp){
					YangStatement grpStatement = grp.writeYang();
					statement.addChild(grpStatement);
				}
			}
		}
		
		if (null != typedefs){
			int gSize = getTypedefsNumber();
			for (int i = 0; i < gSize; i++){
				Typedef grp = getTypedef(i);
				if (null != grp){
					YangStatement grpStatement = grp.writeYang();
					statement.addChild(grpStatement);
				}
			}
		}
		
//		YangStatement path = new YangStatement("path",this.getAbsoultePath());
//		statement.addChild(path);
		
		if (!(this instanceof Case)){
			boolean defalutConfig = true;
			if (null != this.getParent()){
				defalutConfig = ((Node)(this.getParent())).isConfig();
			}

			if (this.isConfig() != defalutConfig) {
				YangStatement config = new YangStatement(
						YangStatement.YANG_STATEMENT_CONFIG,
						(true == this.isConfig) ? "true" : "false");
				statement.addChild(config);
			}
			
			
			
		}

		//container
		if (this instanceof Container){
			Container c = (Container)this;
			if (null != c.getPresence() && (0 != c.getPresence().trim().length())){
				YangStatement presence = new YangStatement(YangStatement.YANG_STATEMENT_PRESENCE,c.getPresence());
				statement.addChild(presence);
			}
		}
		//choice
		else if (this instanceof Choice){
			Choice ch = (Choice)this;
			if (ch.isMandatory() != false){
				YangStatement mandatory = new YangStatement(YangStatement.YANG_STATEMENT_MANDATORY
						,(true == ch.isMandatory())?"true":"false");
				statement.addChild(mandatory);
			}
			
			
			if (null != ch.getDefaultValue()){
				YangStatement dv = new YangStatement(YangStatement.YANG_STATEMENT_DEFAULT
						,ch.getDefaultValue());
				statement.addChild(dv);
			}
		}
		else if (this instanceof Case){
			
		}
		else if (this instanceof Leaf){
			Leaf l = (Leaf)this;
			if (null != l.getType()){
				YangStatement type = l.getType().writeYang();
				statement.addChild(type);
			}
			
			
			if (null != l.getUnits()){
				YangStatement units = new YangStatement(YangStatement.YANG_STATEMENT_UNITS
						,l.getUnits());
				statement.addChild(units);
			}
			if (null != l.getDefaultValue()){
				YangStatement dv = new YangStatement(YangStatement.YANG_STATEMENT_DEFAULT
						,l.getDefaultValue());
				statement.addChild(dv);
			}
			
			if (l.isMandatory() != false){
				YangStatement mandatory = new YangStatement(YangStatement.YANG_STATEMENT_MANDATORY
						,(true == l.isMandatory())?"true":"false");
				statement.addChild(mandatory);
			}
		}
	
		else if (this instanceof LeafList){
			LeafList l = (LeafList)this;
			if (null != l.getType()){
				YangStatement type = l.getType().toYang();
				statement.addChild(type);
			}
			
			
			if (null != l.getUnits()){
				YangStatement units = new YangStatement(YangStatement.YANG_STATEMENT_UNITS
						,l.getUnits());
				statement.addChild(units);
			}
			if (false == l.isUseDefaultMaxElements()){
				YangStatement maxElements = new YangStatement(YangStatement.YANG_STATEMENT_MAXELEMENTS
						,new Integer(l.getMaxElements()).toString());
				statement.addChild(maxElements);
			}
			if (false == l.isUseDefaultMinElements()){
				YangStatement minElements = new YangStatement(YangStatement.YANG_STATEMENT_MINELEMENTS
						,new Integer(l.getMinElements()).toString());
				statement.addChild(minElements);
			}	
			if (null != l.getOrderBy()){
				YangStatement orderbyElement = new YangStatement(YangStatement.YANG_STATEMENT_ORDEREDBY
						,(l.getOrderBy() == OrderBy.SYSTEM)?"system":"user");
				statement.addChild(orderbyElement);
				
			}
		}
		else if (this instanceof YangList){
			YangList l = (YangList)this;
			if (null != l.getKey()){
				YangStatement keys = new YangStatement(YangStatement.YANG_STATEMENT_KEY,l.getKey().toString());
				statement.addChild(keys);
			}
			
			if (0 != l.getUniquesNumber()){
				int size = l.getUniquesNumber();
				for (int i = 0; i < size; i++){
					Unique unique= l.getUnique(i);
					if (null == unique){
						continue;
					}
					YangStatement uniques = new YangStatement(YangStatement.YANG_STATEMENT_UNIQUE,unique.toString());
					statement.addChild(uniques);
				}
				
			}
			
			
			if (false == l.isUseDefaultMaxElements()){
				YangStatement maxElements = new YangStatement(YangStatement.YANG_STATEMENT_MAXELEMENTS
						,new Integer(l.getMaxElements()).toString());
				statement.addChild(maxElements);
			}
			if (false == l.isUseDefaultMinElements()){
				YangStatement minElements = new YangStatement(YangStatement.YANG_STATEMENT_MINELEMENTS
						,new Integer(l.getMinElements()).toString());
				statement.addChild(minElements);
			}	
			
			if (null != l.getOrderBy()){
				YangStatement orderbyElement = new YangStatement(YangStatement.YANG_STATEMENT_ORDEREDBY
						,(l.getOrderBy() == OrderBy.SYSTEM)?"system":"user");
				statement.addChild(orderbyElement);
				
			}
			
		}
		else if (this instanceof Anyxml){
			if (this.isMandatory() != false){
				YangStatement mandatory = new YangStatement(YangStatement.YANG_STATEMENT_MANDATORY
						,(true == this.isMandatory())?"true":"false");
				statement.addChild(mandatory);
			}
		}
		
		//sons
		if(null != this.sons
				&& 0!= getSonsNumber()){
			int size =getSonsNumber();
			for(int i = 0; i < size; i++){
				DataDefElement son = getSon(i);
				if (null != son){
					YangStatement sonElement = son.writeYang();
					if (null != sonElement){
						statement.addChild(sonElement);
					}
				}
			}
		}	
		
		return statement;
	}
	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYin()
	 */
	@Override
	public Element toYin() {
		Element statement = null;
		String statementName = null;
		if (this instanceof Container){
			
			statementName = YangStatement.YANG_STATEMENT_CONTAINER;
		}
		else if (this instanceof Case){
			statementName = YangStatement.YANG_STATEMENT_CASE;
		}
		else if (this instanceof Choice){
			statementName = YangStatement.YANG_STATEMENT_CHOICE;
		}
		else if (this instanceof Leaf){
			statementName = YangStatement.YANG_STATEMENT_LEAF;
		}
		else if (this instanceof LeafList){
			statementName = YangStatement.YANG_STATEMENT_LEAFLIST;
		}
		else if (this instanceof YangList){
			statementName = YangStatement.YANG_STATEMENT_LIST;
		}
		else if (this instanceof Anyxml){
			statementName = YangStatement.YANG_STATEMENT_ANYXML;
		}
		else {
			return null;
		}
		statement = new Element(statementName,env.getNs());
		Attribute name = new Attribute(XMLTag.XML_TAG_NAME,this.name);
		statement.setAttribute(name);
		//when
		if (!isNullString(this.when)){
			Element when = new Element(YangKeyword.WHEN.getKeyword(),env.getNs());
			Attribute condition = new Attribute("condition",this.when);
			when.setAttribute(condition);
			statement.addContent(when);
		}
		//ͨ�ò���
		if (null != this.if_features){
			int size = this.getIf_featuresNumber();
			
			for (int i = 0; i < size; i++){
				String feature = this.getIf_feature(i);
				if (null != feature){
					Element  featureState = 
							new Element(YangKeyword.IFFEATURE.getKeyword(),env.getNs());
					Attribute fname = new Attribute(XMLTag.XML_TAG_NAME,feature);
					featureState.setAttribute(fname);
					statement.addContent(featureState);
				}
			}
			
		}
		//must
		if (0 != this.getMustsNumber()){
			int size = this.getMustsNumber();
			for (int i = 0; i < size; i++){
				Must must = getMust(i);
				if (null != must){
					Element mustStatement = must.writeYin();
					if(null != mustStatement){
						statement.addContent(mustStatement);
					}
					
				}
			}
		}
		if (null != getDescription()){
			Element descr = new Element(YangStatement.YANG_STATEMENT_DESCRIPTION,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(getDescription());
			descr.addContent(text);
			statement.addContent(descr);
		}
		if (null != getReference()){
			Element ref = new Element(YangStatement.YANG_STATEMENT_REFERENCE,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(getReference());
			ref.addContent(text);
			statement.addContent(ref);
		}
		
		if (Status.CURRENT != getStatus()){
			Element status = new Element(YangStatement.YANG_STATEMENT_STATUS,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),this.getStatus().getStatus());
			status.setAttribute(value);
			statement.addContent(status);
		}
		if (null != groupings){
			int gSize = getGroupingsNumber();
			for (int i = 0; i < gSize; i++){
				Grouping grp = getGrouping(i);
				if (null != grp){
					Element grpStatement = grp.writeYin();
					statement.addContent(grpStatement);
				}
			}
		}
		
		if (null != typedefs){
			int gSize = getTypedefsNumber();
			for (int i = 0; i < gSize; i++){
				Typedef grp = getTypedef(i);
				if (null != grp){
					Element grpStatement = grp.writeYin();
					statement.addContent(grpStatement);
				}
			}
		}	
		
//		YangStatement path = new YangStatement("path",this.getAbsoultePath());
//		statement.addChild(path);
		
		if (!(this instanceof Case)){
			boolean defalutConfig = true;
			if (null != this.getParent()){
				defalutConfig = ((Node)(this.getParent())).isConfig();
			}

			if (this.isConfig() != defalutConfig) {
				Element config = new Element(
						YangStatement.YANG_STATEMENT_CONFIG,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
						(true == this.isConfig) ? "true" : "false");
				config.setAttribute(value);
				statement.addContent(config);
			}
			
			
			
		}

		//container
		if (this instanceof Container){
			Container c = (Container)this;
			if (!isNullString(c.getPresence())){
				Element presence = new Element(YangStatement.YANG_STATEMENT_PRESENCE,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(), c.getPresence());
				presence.setAttribute(value);
				statement.addContent(presence);
			}
		}
		//choice
		else if (this instanceof Choice){
			Choice ch = (Choice)this;
			if (ch.isMandatory() != false){
				
				Element mandatory = new Element(
						YangStatement.YANG_STATEMENT_MANDATORY,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
						(true == ch.isMandatory()) ? "true" : "false");
				mandatory.setAttribute(value);
				statement.addContent(mandatory);
			}
			
			
			if (null != ch.getDefaultValue()){
				
				Element dv = new Element(YangStatement.YANG_STATEMENT_DEFAULT,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
						ch.getDefaultValue());		
				dv.setAttribute(value);
				statement.addContent(dv);
			}
		}
		else if (this instanceof Case){
			
		}
		else if (this instanceof Leaf){
			Leaf l = (Leaf)this;
			if (null != l.getType()){
				Element type = l.getType().writeYin();
				statement.addContent(type);
			}
			
			
			if (null != l.getUnits()){
				Element units = new Element(YangStatement.YANG_STATEMENT_UNITS,env.getNs());
				Attribute uname = new  Attribute(XMLTag.XML_TAG_NAME
						,l.getUnits());
				units.setAttribute(uname);
				statement.addContent(units);
			}
			if (null != l.getDefaultValue()){
				Element dv = new Element(YangStatement.YANG_STATEMENT_DEFAULT,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
						l.getDefaultValue());		
				dv.setAttribute(value);
				statement.addContent(dv);
				
			}
			
			if (l.isMandatory() != false){
				Element mandatory = new Element(
						YangStatement.YANG_STATEMENT_MANDATORY,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
						(true == l.isMandatory()) ? "true" : "false");
				mandatory.setAttribute(value);
				statement.addContent(mandatory);
				
			}
		}
	
		else if (this instanceof LeafList){
			LeafList l = (LeafList)this;
			if (null != l.getType()){
				Element type = l.getType().writeYin();
				statement.addContent(type);
			}
				
			if (null != l.getUnits()){
				Element units = new Element(YangStatement.YANG_STATEMENT_UNITS,env.getNs());
				Attribute uname = new  Attribute(XMLTag.XML_TAG_NAME
						,l.getUnits());
				units.setAttribute(uname);
				statement.addContent(units);
			}
			if (false == l.isUseDefaultMaxElements()){
				
				Element maxElements = new Element(YangStatement.YANG_STATEMENT_MAXELEMENTS,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
						,new Integer(l.getMaxElements()).toString());
				maxElements.setAttribute(value);
				statement.addContent(maxElements);
			}
			if (false == l.isUseDefaultMinElements()){
				Element minElements = new Element(YangStatement.YANG_STATEMENT_MINELEMENTS,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
						,new Integer(l.getMinElements()).toString());
				minElements.setAttribute(value);
				statement.addContent(minElements);
			}	
			if (null != l.getOrderBy()){
				Element orderbyElement = new Element(YangStatement.YANG_STATEMENT_ORDEREDBY,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
						,(l.getOrderBy() == OrderBy.SYSTEM)?"system":"user");
				orderbyElement.setAttribute(value);
				statement.addContent(orderbyElement);
				
			}
		}
		else if (this instanceof YangList){
			YangList l = (YangList)this;
			if (null != l.getKey()){
				Element keys = new Element(YangStatement.YANG_STATEMENT_KEY,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
						,l.getKey().toString());
				keys.setAttribute(value);
				statement.addContent(keys);
			}
			
			if (0 != l.getUniquesNumber()){
				int size = l.getUniquesNumber();
				for (int i = 0; i < size; i++){
					Unique unique = l.getUnique(i);
					if(null == unique){
						continue;
					}
					
					Element uniques = new Element(YangStatement.YANG_STATEMENT_UNIQUE,env.getNs());
					Attribute tag = new Attribute(XMLTag.XML_TAG_TAG
							,unique.toString());
					uniques.setAttribute(tag);
					statement.addContent(uniques);
				}
				
				
			}
			
			
			if (false == l.isUseDefaultMaxElements()){
				Element maxElements = new Element(YangStatement.YANG_STATEMENT_MAXELEMENTS,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
						,new Integer(l.getMaxElements()).toString());
				maxElements.setAttribute(value);
				statement.addContent(maxElements);
			}
			if (false == l.isUseDefaultMinElements()){
				Element minElements = new Element(YangStatement.YANG_STATEMENT_MINELEMENTS,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
						,new Integer(l.getMinElements()).toString());
				minElements.setAttribute(value);
				statement.addContent(minElements);
			}				
			if (null != l.getOrderBy()){
				Element orderbyElement = new Element(YangStatement.YANG_STATEMENT_ORDEREDBY,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
						,(l.getOrderBy() == OrderBy.SYSTEM)?"system":"user");
				orderbyElement.setAttribute(value);
				statement.addContent(orderbyElement);
				
			}
		}
		else if (this instanceof Anyxml){
			if (this.isMandatory() != false){
				Element mandatory = new Element(
						YangStatement.YANG_STATEMENT_MANDATORY,env.getNs());
				Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
						(true == this.isMandatory()) ? "true" : "false");
				mandatory.setAttribute(value);
				statement.addContent(mandatory);
				
			}
		}
		//sons
		if(null != this.sons && 0!= getSonsNumber() ){
			int size = getSonsNumber();
			for(int i = 0; i < size; i++){
				DataDefElement son = getSon(i);
				if (null != son){
					Element sonElement = son.writeYin();
					if (null != sonElement){
						statement.addContent(sonElement);
					}
				}
			}
		}
		
		return statement;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toXML()
	 */
	@Override
	public Element toXML() {
		Element node = new Element(XMLTag.XML_TAG_NODE);
		Element nodeType = null;
		Element name = null;
		if (this instanceof Container){
			nodeType = new Element(XMLTag.XML_TAG_CONTAINER);
		}
		else if (this instanceof Case){
			nodeType  = new Element(XMLTag.XML_TAG_CASE);
			name = new Element(XMLTag.XML_TAG_VALUE);
			name.setText(this.name);
		}
		else if (this instanceof Choice){
			nodeType = new Element(XMLTag.XML_TAG_CHOICE);
		}
		else if (this instanceof Leaf){
			nodeType = new Element(XMLTag.XML_TAG_LEAF);
		}
		else if (this instanceof LeafList){
			nodeType = new Element(XMLTag.XML_TAG_LEAFLIST);
		}
		else if (this instanceof YangList){
			nodeType = new Element(XMLTag.XML_TAG_LIST);
		}
		else {
			return null;
		}

		if (null == name){
			name = new Element(XMLTag.XML_TAG_NAME);
			name.setText(this.name);
		}
	
		node.addContent(nodeType);
		nodeType.addContent(name);
		
		Element root = nodeType;
		this.getEnv().setTemp(root);
		
		//ͨ�ò���
		if (null != this.if_features){
			int size = this.getIf_featuresNumber();
			
			for (int i = 0; i < size; i++){
				String feature = this.getIf_feature(i);
				if (null != feature){
					Element  featureState = 
							new Element(XMLTag.XML_TAG_IFFEATURE);
					featureState.addContent(feature);
					root.addContent(featureState);
				}
			}
			
		}
		if (null != this.description){
			Element descr = new Element(XMLTag.XML_TAG_DESCRIPTION);
			descr.setText(this.description);
			root.addContent(descr);
		}
//		if (null != this.nativeDescr){
//			Element nativedescr = new Element(XMLTag.XML_TAG_NATIVEDESCR);
//			nativedescr.setText(this.nativeDescr);
//			root.addContent(nativedescr);
//		}
		if (null != this.reference){
			Element ref = new Element(XMLTag.XML_TAG_REFERENCE);
			ref.setText(this.reference);
			root.addContent(ref);
		}
		

				
		if (!Status.CURRENT.equals(this.status)) {
			Element status = new Element(XMLTag.XML_TAG_STATUS);
			status.setText(this.status.getStatus());
			root.addContent(status);
		}

//		Element status = new Element(XMLTag.XML_TAG_STATUS);
//		status.setText(this.status.getStatus());
//		root.addContent(status);
		
		if (!(this instanceof Case)){
			Element config = new Element(XMLTag.XML_TAG_CONFIG);
			config.setText((true == this.isConfig)?"true":"false");
			root.addContent(config);
		}
		
		//container
		if (this instanceof Container){
			Container c = (Container)this;
			if (null != c.getPresence() && (0 != c.getPresence().trim().length())){
				Element presence = new Element(XMLTag.XML_TAG_PRESENCE);
				presence.setText(c.getPresence());
				root.addContent(presence);
			}
		}
		//choice
		else if (this instanceof Choice){
			Choice ch = (Choice)this;
			Element mandatory = new Element(XMLTag.XML_TAG_MANDATORY);
			mandatory.setText((true == ch.isMandatory())?"true":"false");
			root.addContent(mandatory);
			
			if (null != ch.getDefaultValue()){
				Element dv = new Element(XMLTag.XML_TAG_DEFAULT);
				dv.setText(ch.getDefaultValue());
				root.addContent(dv);
			}
		}
		else if (this instanceof Case){
			
		}
		else if (this instanceof Leaf){
			Leaf l = (Leaf)this;
			if (null != l.getType()){
				Element type = l.getType().writeXML();
				root.addContent(type);
			}
			
			
			if (null != l.getUnits()){
				Element units = new Element(XMLTag.XML_TAG_UNITS);
				units.setText(l.getUnits());
				root.addContent(units);
			}
			if (null != l.getDefaultValue()){
				Element dv = new Element(XMLTag.XML_TAG_DEFAULT);
				dv.setText(l.getDefaultValue());
				root.addContent(dv);
			}
			Element mandatory = new Element(XMLTag.XML_TAG_MANDATORY);
			mandatory.setText((true == l.isMandatory())?"true":"false");
			root.addContent(mandatory);

		}
		//TODO:�ݲ�֧��
		else if (this instanceof LeafList){
			
		}
		else if (this instanceof YangList){
			YangList l = (YangList)this;
//			if (null != l.getKeysEx()){
//				Element keysElement = new Element(XMLTag.XML_TAG_KEYS);
//				root.addContent(keysElement);
//				String[] keys = l.getKeyExs();
//				int keysSize = keys.length;
//				for (int i = 0;i < keysSize; i++){
//					String key = keys[i];
//					if (null != key){
//						Element keyelement = new Element(XMLTag.XML_TAG_KEY);
//						keyelement.setText(key.trim());
//						keysElement.addContent(keyelement);
//					}
//				}
//			}
//			
//			if (null != l.getUniquesEx()){
//				Element uniquesElement = new Element(XMLTag.XML_TAG_UNIQUES);
//				root.addContent(uniquesElement);
//				String[] uniques = l.getUniqueExs();
//				int uniquesSize = uniques.length;
//				for (int i = 0;i < uniquesSize; i++){
//					String uni = uniques[i];
//					if (null != uni){
//						Element unique = new Element(XMLTag.XML_TAG_UNIQUE);
//						unique.setText(uni.trim());
//						uniquesElement.addContent(unique);
//					}
//				}	
//			}
//			

			
			if (false == l.isUseDefaultMaxElements()){
				Element maxElements = new Element(XMLTag.XML_TAG_MAXELEMENTS);
				maxElements.setText(new Integer(l.getMaxElements()).toString());
				root.addContent(maxElements);
			}
			if (false == l.isUseDefaultMinElements()){
				Element minElements = new Element(XMLTag.XML_TAG_MINELEMENTS);
				minElements.setText(new Integer(l.getMinElements()).toString());
				root.addContent(minElements);
			}				
			
		}
		
		//sons
		if(null != this.sons
				&& 0 != getSonsNumber()){
			int size = getSonsNumber();
			for(int i = 0; i < size; i++){
				DataDefElement son = getSon(i);
				if (null != son){
					Element sonElement = son.writeXML();
					if (null != sonElement){
						root.addContent(sonElement);
					}
				}
			}
		}
		
		return node;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#isFieldMandatory(java.lang.String)
	 */
	@Override
	public boolean isFieldMandatory(String field) {
		// TODO Auto-generated method stub
		return false;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readXML(org.jdom2.Element)
	 */
	@Override
	public int readXML(Element element) throws ModelException {
		if (null == element){
			return MODELELEMENT_OK;
		}
		
		int result = MODELELEMENT_OK;
		Element child = element;

		Env subEnv = newSubEnv();
		// �ӽڵ�
		if (XMLTag.XML_TAG_NODE.equals(child.getName())) {
			if (this instanceof Leaf
					|| this instanceof LeafList){
				return MODELELEMENT_FAIL;
			}

			Node childNode = (Node) ModelElement.parseXML(subEnv, child);
			if (null != childNode) {
				if ((this instanceof Choice) && !(childNode instanceof Case)){
					Case c = new Case(subEnv,childNode.getName());
					c.addSon(childNode,false);
					this.addSon(c,false);
				}
				else {
					addSon(childNode,false);					
				}
			}
			

		}
		// ͨ�ò���
		// ����
		else if (child.getName().equals(XMLTag.XML_TAG_DESCRIPTION)) {
			this.setDescription(child.getText());
		}
//		else if (child.getName().equals(XMLTag.XML_TAG_NATIVEDESCR)) {
//			this.setNativeDescr(child.getText());
//		}
		// reference
		else if (child.getName().equals(XMLTag.XML_TAG_REFERENCE)) {
			this.setReference(child.getText());
		}
		// status
		else if (child.getName().equals(XMLTag.XML_TAG_STATUS)) {
			this.setStatus(Status.getStatus(child.getText()));
		}
		// config
		else if (child.getName().equals(XMLTag.XML_TAG_CONFIG)) {
			String config = child.getText();
			if (null != config) {
				if (config.equals("true")) {
					this.setConfig(true);
				} else if (config.equals("false")) {
					this.setConfig(false);
				} else {
					return MODELELEMENT_FAIL;
				}
			}
		}
		// if_feature
		else if (child.getName().equals(
				XMLTag.XML_TAG_IFFEATURE)) {
			this.addIf_feature(child.getText());
		}
		// ��ͨ�ò���
		// presence
		else if (child.getName().equals(XMLTag.XML_TAG_PRESENCE)) {
			if (!(this instanceof Container)) {
				return MODELELEMENT_FAIL;
			}
			Container c = (Container) this;			
			c.setPresence(child.getText());
		}
		// mandatory
		else if (child.getName().equals(XMLTag.XML_TAG_MANDATORY)) {
			if (!(this instanceof Choice) && !(this instanceof Leaf)) {
				return MODELELEMENT_FAIL;
			}
			String mandatory = child.getText();

			if (null != mandatory) {
				if (mandatory.equals("true")) {
					if (this instanceof Choice) {
						((Choice) this).setMandatory(true);
					} else {
						((Leaf) this).setMandatory(true);
					}
				} else if (mandatory.equals("false")) {
					if (this instanceof Choice) {
						((Choice) this).setMandatory(false);
					} else {
						((Leaf) this).setMandatory(false);
					}
				} else {
					return MODELELEMENT_FAIL;
				}
			}
		}
		// default
		else if (child.getName().equals(XMLTag.XML_TAG_DEFAULT)) {
			if (this instanceof Choice) {
				((Choice) (this)).setDefaultValue(child.getText());
			} else if (this instanceof Leaf) {
				((Leaf) (this)).setDefaultValue(child.getText());
			} else {
				return MODELELEMENT_FAIL;
			}
		}
		// type
		else if (child.getName().equals(XMLTag.XML_TAG_TYPE)) {
			if (this instanceof Leaf || this instanceof LeafList) {

				Type type = (Type) ModelElement.parseXML(subEnv, child);
				if (null == type) {
					return MODELELEMENT_FAIL;
				}

				if (this instanceof Leaf) {
					((Leaf) (this)).setType(type);
				} else {
					((LeafList) (this)).setType(type);
				}
			}

			else {
				return MODELELEMENT_FAIL;
			}
		}
		// units
		else if (child.getName().equals(XMLTag.XML_TAG_UNITS)) {
			if (this instanceof Leaf) {
				Leaf l = (Leaf) this;
				l.setUnits(child.getText());
			} else if (this instanceof LeafList) {
				LeafList l = (LeafList) this;
				l.setUnits(child.getText());
			} else {
				return MODELELEMENT_FAIL;
			}

		}
		// key
//		else if (child.getName().equals(XMLTag.XML_TAG_KEYS)) {
//			if (this instanceof YangList) {
//				YangList l = (YangList) this;
//				List<Element> keys = child.getChildren();
//				if (null == keys) {
//					return MODELELEMENT_FAIL;
//				}
//				int keysize = keys.size();
//				for (int j = 0; j < keysize; j++) {
//					Element key = keys.get(j);
//					if (null == key) {
//						continue;
//					}
//					if (!key.getName().equals(XMLTag.XML_TAG_KEY)) {
//						return MODELELEMENT_FAIL;
//					}
//					l.addKeysEx(key.getText());
//
//				}
//
//			} else {
//				return MODELELEMENT_FAIL;
//			}
//
//		}
		// unique
//		else if (child.getName().equals(XMLTag.XML_TAG_UNIQUES)) {
//			if (this instanceof YangList) {
//				YangList l = (YangList) this;
//				List<Element> uniques = child.getChildren();
//				if (null == uniques) {
//					return MODELELEMENT_FAIL;
//				}
//				int uniquesize = uniques.size();
//				for (int j = 0; j < uniquesize; j++) {
//					Element unique = uniques.get(j);
//					if (null == unique) {
//						continue;
//					}
//					if (!unique.getName().equals(XMLTag.XML_TAG_UNIQUE)) {
//						return MODELELEMENT_FAIL;
//					}
//					l.addUniquesEx(unique.getText());
//
//				}
//			} else {
//				return MODELELEMENT_FAIL;
//			}
//
//		}
		
		// maxElements
		else if (child.getName().equals(XMLTag.XML_TAG_MAXELEMENTS)) {
			if (this instanceof YangList) {
				YangList l = (YangList) this;
				l.setMaxElements(new Integer(child.getText()).intValue());
			} else if (this instanceof LeafList) {
				LeafList l = (LeafList) this;
				l.setMaxElements(new Integer(child.getText()).intValue());
			} else {
				return MODELELEMENT_FAIL;
			}

		}
		// minElements
		else if (child.getName().equals(XMLTag.XML_TAG_MINELEMENTS)) {
			if (this instanceof YangList) {
				YangList l = (YangList) this;
				l.setMinElements(new Integer(child.getText()).intValue());
			} else if (this instanceof LeafList) {
				LeafList l = (LeafList) this;
				l.setMinElements(new Integer(child.getText()).intValue());
			} else {
				return MODELELEMENT_FAIL;
			}

		}
		
		else if (child.getName().equals(XMLTag.XML_TAG_NAME)
				|| child.getName().equals(XMLTag.XML_TAG_VALUE)){
			return MODELELEMENT_OK;
		}
		else {
			return MODELELEMENT_FAIL;
		}
	
		return MODELELEMENT_OK;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYANG(com.netscenery.modeldesigner.util.YangStatement)
	 */
	@Override
	public int readYANG(YangStatement statement) throws YangParserException, ModelException {
		if (null == statement){
			return MODELELEMENT_OK;
		}

			String value = statement.getArgument();
			//ͨ�ò���
			//����
			if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_DESCRIPTION)){
				this.setDescription(value);
			}
		    //reference
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_REFERENCE)){
				this.setReference(value);
			}
		    //status
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_STATUS)){
				this.setStatus(Status.getStatus(value));
			}
			//when
			else if (statement.getKeyword().equals(YangKeyword.WHEN.getKeyword())){
				this.setWhen(value);
			}
		    //config
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_CONFIG)){
				if (null != value){
					if (value.equals("true")){
						this.setConfig(true);
					}
					else if (value.equals("false")){
						this.setConfig(false);
					}
					else {
						return MODELELEMENT_FAIL;
					}
				}
			}	
			// if-feature
			else if (statement.getKeyword().equals(
					YangStatement.YANG_STATEMENT_IFFEATURE)) {
				this.addIf_feature(value);
			}
			//��ͨ�ò���
			//presence
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_PRESENCE)){
				if (!(this instanceof Container)){
					return MODELELEMENT_FAIL;
				}
				Container c = (Container)this;
				c.setPresence(value);
			}	
			//mandatory
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_MANDATORY)){
				if (!(this instanceof Choice)
						&& !(this instanceof Leaf)
						&& !(this instanceof Anyxml)){
					return MODELELEMENT_FAIL;
				}

				if (null != value){
					if (value.equals("true")){
						if (this instanceof Choice){
							((Choice)this).setMandatory(true);
						}
						else if (this instanceof Leaf) {
							((Leaf)this).setMandatory(true);
						}
						else {
							((Anyxml)this).setMandatory(true);
						}
					}
					else if (value.equals("false")){
						if (this instanceof Choice){
							((Choice)this).setMandatory(false);
						}
						else if (this instanceof Leaf){
							((Leaf)this).setMandatory(false);
						}
						else {
							((Anyxml)this).setMandatory(false);
						}
					}
					else {
						return MODELELEMENT_FAIL;
					}
				}
			}	
			//default
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_DEFAULT)){
				if (this instanceof Choice){
					((Choice)(this)).setDefaultValue(value);
				}
				else if (this instanceof Leaf){
					((Leaf)(this)).setDefaultValue(value);
				}
				else {
					return MODELELEMENT_FAIL;
				}
			}
			//type
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_TYPE)){
				if (this instanceof Leaf
						|| this instanceof LeafList){
					Env subEnv = newSubEnv();
					Type type = (Type) ModelElement.parseYANG(subEnv, statement);
					if (null == type){
						return MODELELEMENT_FAIL;
					}
					if (this instanceof Leaf){
						((Leaf)(this)).setType(type);
					}
					else {
						((LeafList)(this)).setType(type);
					}
				}

				else {
					return MODELELEMENT_FAIL;
				}
			}	
			//units
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_UNITS)){
				if (this instanceof Leaf){
					Leaf l = (Leaf)this;
					l.setUnits(value);
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					l.setUnits(value);
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}	
			//key
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_KEY)){
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.setKey(new Field(value));
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}	
			//unique
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_UNIQUE)){
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.addUnique(new Unique(l,value));
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}	

			//maxElements
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_MAXELEMENTS)){
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.setMaxElements(new Integer(value).intValue());
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					l.setMaxElements(new Integer(value).intValue());
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}			
			//minElements
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_MINELEMENTS)){
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.setMinElements(new Integer(value).intValue());
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					l.setMinElements(new Integer(value).intValue());
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}
			//order-by
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_ORDEREDBY)){
				if (this instanceof YangList){
					YangList l = (YangList)this;
					if (value.equals("system")){
						l.setOrderBy(OrderBy.SYSTEM);
					}
					else if (value.equals("user")){
						l.setOrderBy(OrderBy.USER);
					}
					else {
						return MODELELEMENT_FAIL;
					}
					
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					if (value.equals("system")){
						l.setOrderBy(OrderBy.SYSTEM);
					}
					else if (value.equals("user")){
						l.setOrderBy(OrderBy.USER);
					}
					else {
						return MODELELEMENT_FAIL;
					}
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}
			//sons
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_CONTAINER)
					|| statement.getKeyword().equals(YangStatement.YANG_STATEMENT_CASE)
					|| statement.getKeyword().equals(YangStatement.YANG_STATEMENT_CHOICE)
					|| statement.getKeyword().equals(YangStatement.YANG_STATEMENT_LEAF)
					|| statement.getKeyword().equals(YangStatement.YANG_STATEMENT_LEAFLIST)
					|| statement.getKeyword().equals(YangStatement.YANG_STATEMENT_LIST)
					|| statement.getKeyword().equals(YangStatement.YANG_STATEMENT_ANYXML)
					|| statement.getKeyword().equals(YangStatement.YANG_STATEMENT_USES)
					){
				if (this instanceof Leaf
						|| this instanceof LeafList
						|| this instanceof Anyxml){
					return MODELELEMENT_FAIL;
				}
				Env subEnv = newSubEnv();
				DataDefElement subnode = (DataDefElement) ModelElement.parseYANG(subEnv, statement);
				if ((this instanceof Choice) && !(subnode instanceof Case)){
					Case c = new Case(subEnv,subnode.getName());
					c.addSon(subnode,false);
					this.addSon(c,false);
				}
				else {
					this.addSon(subnode,false);
				}
				
				
			}
			
			else if (statement.getKeyword().equals(YangStatement.YANG_STATEMENT_MUST)){
				if (this instanceof Choice 
						|| this instanceof Case){
					return MODELELEMENT_FAIL;
				}
				Env subEnv = newSubEnv();
				Must must = (Must) ModelElement.parseYANG(subEnv, statement);
				this.addMust(must);
			}
			else if (statement.getKeyword().equals(YangKeyword.GROUPING.getKeyword())){
				Grouping grp = (Grouping) ModelElement.parseYANG(newSubEnv(), statement);
				this.addGrouping(grp);
			}
			else if (statement.getKeyword().equals(YangKeyword.TYPEDEF.getKeyword())){
				Typedef def = (Typedef) ModelElement.parseYANG(newSubEnv(), statement);
				this.addTypedef(def);
			}
			else {
				return MODELELEMENT_FAIL;
			}

			
		
		return MODELELEMENT_OK;
	}
	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYANG(com.netscenery.modeldesigner.util.YangStatement)
	 */
	@Override
	public int readYin(Element statement) throws ModelException {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		
		int result = MODELELEMENT_OK;

			//ͨ�ò���
			//����
			if (statement.getName().equals(YangStatement.YANG_STATEMENT_DESCRIPTION)){
				Element text = statement.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
				if (null == text){
					return MODELELEMENT_FAIL;
				}
				this.setDescription(text.getText());
			}
		    //reference		
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_REFERENCE)){
				
				Element text = statement.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
				if (null == text){
					return MODELELEMENT_FAIL;
				}
				this.setReference(text.getText());
			}
		    //status
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_STATUS)){
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (null == value){
					return MODELELEMENT_FAIL;
				}
				else {
					this.status = Status.getStatus(value);
				}
				
			}
			//when
			else if (statement.getName().equals(YangKeyword.WHEN.getKeyword())){
				this.setWhen(statement.getAttributeValue("condition", env.getNs()));
			}
		    //config
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_CONFIG)){
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (null != value){
					if (value.equals("true")){
						this.setConfig(true);
					}
					else if (value.equals("false")){
						this.setConfig(false);
					}
					else {
						return MODELELEMENT_FAIL;
					}
				}
				else {
					return MODELELEMENT_FAIL;
				}
			}	
			// if-feature
			else if (statement.getName().equals(
					YangStatement.YANG_STATEMENT_IFFEATURE)) {
				String value= statement.getAttributeValue(XMLTag.XML_TAG_NAME);
				if (null == value){
					return MODELELEMENT_FAIL;
				}
				this.addIf_feature(value);
			}
			//��ͨ�ò���
			//presence
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_PRESENCE)){
				if (!(this instanceof Container)){
					return MODELELEMENT_FAIL;
				}
				Container c = (Container)this;
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if(isNullString(value)){
					return MODELELEMENT_FAIL;
				}
				c.setPresence(value);
			}	
			//mandatory
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_MANDATORY)){
				if (!(this instanceof Choice)
						&& !(this instanceof Leaf)){
					return MODELELEMENT_FAIL;
				}
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (!isNullString(value)){
					if (value.equals("true")){
						if (this instanceof Choice){
							((Choice)this).setMandatory(true);
						}
						else {
							((Leaf)this).setMandatory(true);
						}
					}
					else if (value.equals("false")){
						if (this instanceof Choice){
							((Choice)this).setMandatory(false);
						}
						else {
							((Leaf)this).setMandatory(false);
						}
					}
					else {
						return MODELELEMENT_FAIL;
					}
				}
				else {
					return MODELELEMENT_FAIL;
				}
			}	
			//default
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_DEFAULT)){
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (isNullString(value)){
					return MODELELEMENT_FAIL;
				}
				if (this instanceof Choice){
					((Choice)(this)).setDefaultValue(value);
				}
				else if (this instanceof Leaf){
					((Leaf)(this)).setDefaultValue(value);
				}
				else {
					return MODELELEMENT_FAIL;
				}
			}
			//type
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_TYPE)){
				if (this instanceof Leaf
						|| this instanceof LeafList){
					Env subEnv = newSubEnv();
					Type type = (Type) ModelElement.parseYin(subEnv, statement);
					if (null == type){
						return MODELELEMENT_FAIL;
					}
					if (this instanceof Leaf){
						((Leaf)(this)).setType(type);
					}
					else {
						((LeafList)(this)).setType(type);
					}
				}

				else {
					return MODELELEMENT_FAIL;
				}
			}	
			//units
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_UNITS)){
				String value= statement.getAttributeValue(XMLTag.XML_TAG_NAME);
				if (isNullString(value)){
					return MODELELEMENT_FAIL;
				}
				if (this instanceof Leaf){
					Leaf l = (Leaf)this;
					l.setUnits(value);
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					l.setUnits(value);
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}	
			//key
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_KEY)){
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (isNullString(value)){
					return MODELELEMENT_FAIL;
				}
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.setKey(new Field(value));
				}
				else {
					return MODELELEMENT_FAIL;
				}
				  
			}	
			//unique
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_UNIQUE)){
				String value= statement.getAttributeValue(XMLTag.XML_TAG_TAG);
				if (isNullString(value)){
					return MODELELEMENT_FAIL;
				}
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.addUnique(new Unique(l,value));
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}	
			//maxElements
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_MAXELEMENTS)){
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (isNullString(value)){
					return MODELELEMENT_FAIL;
				}
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.setMaxElements(new Integer(value).intValue());
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					l.setMaxElements(new Integer(value).intValue());
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}			
			//minElements
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_MINELEMENTS)){
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (isNullString(value)){
					return MODELELEMENT_FAIL;
				}
				if (this instanceof YangList){
					YangList l = (YangList)this;
					l.setMinElements(new Integer(value).intValue());
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					l.setMinElements(new Integer(value).intValue());
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}	
			//order-by
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_ORDEREDBY)){
				String value= statement.getAttributeValue(YangKeyword.VALUE.getKeyword());
				if (this instanceof YangList){
					YangList l = (YangList)this;
					if (value.equals("system")){
						l.setOrderBy(OrderBy.SYSTEM);
					}
					else if (value.equals("user")){
						l.setOrderBy(OrderBy.USER);
					}
					else {
						return MODELELEMENT_FAIL;
					}
					
				}
				else if (this instanceof LeafList){
					LeafList l = (LeafList)this;
					if (value.equals("system")){
						l.setOrderBy(OrderBy.SYSTEM);
					}
					else if (value.equals("user")){
						l.setOrderBy(OrderBy.USER);
					}
					else {
						return MODELELEMENT_FAIL;
					}
				}
				else {
					return MODELELEMENT_FAIL;
				}
				
			}
			//subnodes
			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_CONTAINER)
					|| statement.getName().equals(YangStatement.YANG_STATEMENT_CASE)
					|| statement.getName().equals(YangStatement.YANG_STATEMENT_CHOICE)
					|| statement.getName().equals(YangStatement.YANG_STATEMENT_LEAF)
					|| statement.getName().equals(YangStatement.YANG_STATEMENT_LEAFLIST)
					|| statement.getName().equals(YangStatement.YANG_STATEMENT_LIST)){
				if (this instanceof Leaf
						|| this instanceof LeafList){
					return MODELELEMENT_FAIL;
				}
				Env subEnv = newSubEnv();
				Node subnode = (Node) ModelElement.parseYin(subEnv, statement);
				if ((this instanceof Choice) && !(subnode instanceof Case)){
					Case c = new Case(subEnv,subnode.getName());
					c.addSon(subnode,false);
					this.addSon(c,false);
				}
				else {
					this.addSon(subnode,false);
				}
				
				
			}

			else if (statement.getName().equals(YangStatement.YANG_STATEMENT_MUST)
					){
				if (this instanceof Choice 
						|| this instanceof Case){
					return MODELELEMENT_FAIL;
				}
				Env subEnv = newSubEnv();
				Must must = (Must) ModelElement.parseYin(subEnv, statement);
				this.addMust(must);
			}
			else if (statement.getName().equals(YangKeyword.GROUPING.getKeyword())){
				Grouping grp = (Grouping) ModelElement.parseYin(newSubEnv(), statement);
				this.addGrouping(grp);
			}
			else if ( statement.getName().equals(YangKeyword.TYPEDEF.getKeyword())){
				Typedef def  = (Typedef) ModelElement.parseYin(newSubEnv(), statement);
				this.addTypedef(def);
			}
			else {
				return MODELELEMENT_FAIL;
			}

			
		
		return MODELELEMENT_OK;
	}
	public static Node create(Env env, Element element) throws ModelException{
		if (null == element){
			return null;
		}
		
		if (!element.getName().equals(XMLTag.XML_TAG_NODE)){
			return null;
		}
		
		List<Element> children = element.getChildren();
		if (null == children
				|| (children.size() != 1)){
			return null;
		}
		
		Element nodeType = children.get(0);
		if (null == nodeType){
			return null;
		}
		Element name = null;
		if (nodeType.getName().equals(XMLTag.XML_TAG_CASE)){
			name = nodeType.getChild(XMLTag.XML_TAG_VALUE);
		}
		else {
			name = nodeType.getChild(XMLTag.XML_TAG_NAME);
		}
		
		if (null == name){
			return null;
		}
		
		return create(env,nodeType.getName(),name.getText());
	}
	public static Node create(Env env, YangStatement statement) throws ModelException{
		if (null == statement){
			return null;
		}
		
		
		return create(env,statement.getKeyword(),statement.getArgument());
	}

	public static Node create(Env env, String nodeType, String nodeName) throws ModelException{
		if (null == nodeType){
			return null;
		}
		
		if (null == nodeName){
			return null;
		}
		

		Node node = null;
		if (nodeType.equals(YangStatement.YANG_STATEMENT_CASE)){
			node = new Case(env,nodeName);
		}
		else if (nodeType.equals(YangStatement.YANG_STATEMENT_CHOICE)){
			node = new Choice(env,nodeName);
		}
		else if (nodeType.equals(YangStatement.YANG_STATEMENT_CONTAINER)){
			node = new Container(env,nodeName);
		}		
		else if (nodeType.equals(YangStatement.YANG_STATEMENT_LEAF)){
			node = new Leaf(env,nodeName);
		}		
		else if (nodeType.equals(YangStatement.YANG_STATEMENT_LEAFLIST)){
			node = new LeafList(env,nodeName);
		}
		else if (nodeType.equals(YangStatement.YANG_STATEMENT_LIST)){
			node = new YangList(env,nodeName);
		}
		else if (nodeType.equals(YangStatement.YANG_STATEMENT_ANYXML)){
			node = new Anyxml(env,nodeName);
		}
		else {
			return null;
		}
		
		return node;
	}
	
	public  MapInfo getMapInfo() throws SecurityException, NoSuchMethodException {
		MapInfo mapInfo = new MapInfo();
		mapInfo.setClazz(this.getClass());
		//basic Fields
		//description
		LeafFieldMap descr = new LeafFieldMap();
		descr.setFieldName("description");
		mapInfo.addBasicField(descr);
		//reference
		LeafFieldMap reference = new LeafFieldMap();
		reference.setFieldName("reference");
		mapInfo.addBasicField(reference);
		//status
		LeafFieldMap status = new LeafFieldMap();
		status.setFieldName("status");
		status.setElementClass(Status.class);
		mapInfo.addBasicField(status);
		//if-feature
		ListFieldMap if_feature = new ListFieldMap();
		if_feature.setFieldName("if_feature");
		if_feature.setDisplayName("if-feature");
		mapInfo.addBasicField(if_feature);
		if (this instanceof Case){
		}
		else if (this instanceof Choice){

			//config
			LeafFieldMap config = new LeafFieldMap();
			config.setFieldName("config");
			config.setElementClass(Boolean.class);
			mapInfo.addBasicField(config);

			LeafFieldMap mandatory = new LeafFieldMap();
			mandatory.setFieldName("mandatory");
			mandatory.setElementClass(Boolean.class);
			mapInfo.addBasicField(mandatory);

			LeafFieldMap defaultValue = new LeafFieldMap();
			defaultValue.setFieldName("default");
			mapInfo.addBasicField(defaultValue);
			
		}
		else if (this instanceof Container){

			// config
			LeafFieldMap config = new LeafFieldMap();
			config.setFieldName("config");
			config.setElementClass(Boolean.class);
			mapInfo.addBasicField(config);

			// presence
			LeafFieldMap presence = new LeafFieldMap();
			presence.setFieldName("presence");
			mapInfo.addBasicField(presence);
			
		}
		else if (this instanceof Leaf){

			// config
			LeafFieldMap config = new LeafFieldMap();
			config.setFieldName("config");
			config.setElementClass(Boolean.class);
			mapInfo.addBasicField(config);

			LeafFieldMap type = new LeafFieldMap();
			type.setElementClass(Type.class);
			type.setFieldName("type");
//			MethodInfo createType = new MethodInfo();
//			createType.setMethod(this.getClass().getMethod("createType", String.class,String.class));
//			Parameter[] paras = new Parameter[2];
//			ArrayList<String> builtinTypes = BuiltinType.getBuiltinTypes();
//			Parameter pBuiltinType = new Parameter("builtinType",builtinTypes,true,true);
//			paras[0]= pBuiltinType;
//			MethodInfo derivedTypes = new MethodInfo();
//			derivedTypes.setMethod(Type.class.getMethod("getAvailableDerivedTypes", Env.class,String.class));
//			Parameter[] pderivedTypeMethods = new Parameter[2];
//			MethodInfo env = new MethodInfo();
//			env.setMethod(this.getClass().getMethod("newSubEnv", null));
//			pderivedTypeMethods[0] = new Parameter("env",env,false,true);
//			pderivedTypeMethods[1] = new Parameter("builtinType",false,true);
//			pderivedTypeMethods[1].setRefer(paras[0]);
//			derivedTypes.setMethodParas(pderivedTypeMethods);
//			paras[1] = new Parameter("derviedType",derivedTypes,true,false);
//			createType.setMethodParas(paras);
//			type.setCreate(createType);
			mapInfo.addBasicField(type);

			LeafFieldMap units = new LeafFieldMap();
			units.setFieldName("units");
			mapInfo.addBasicField(units);

			LeafFieldMap mandatory = new LeafFieldMap();
			mandatory.setFieldName("mandatory");
			mandatory.setElementClass(Boolean.class);
			mapInfo.addBasicField(mandatory);

			LeafFieldMap defaultValue = new LeafFieldMap();
			defaultValue.setFieldName("default");
			mapInfo.addBasicField(defaultValue);
		
		}
		else if (this instanceof YangList){

			//config

			LeafFieldMap config = new LeafFieldMap();
			config.setFieldName("config");
			config.setElementClass(Boolean.class);
			mapInfo.addBasicField(config);

			ListFieldMap key = new ListFieldMap();
			key.setFieldName("key");
			mapInfo.addBasicField(key);

			ListFieldMap unique = new ListFieldMap();
			unique.setFieldName("unique");
			mapInfo.addBasicField(unique);
			
			

			LeafFieldMap maxElements = new LeafFieldMap();
			maxElements.setFieldName("max-elements");
			maxElements.setElementClass(Integer.class);
			mapInfo.addBasicField(maxElements);

			LeafFieldMap minElements = new LeafFieldMap();
			minElements.setFieldName("min-elements");
			minElements.setElementClass(Integer.class);
			mapInfo.addBasicField(minElements);			
		}
		else {
			return null;
		}
		
		//�ӽڵ�
		if( !((this instanceof Leaf)
				|| (this instanceof LeafList))){
			ListFieldMap node = new ListFieldMap();
			node.setDisplayName("node");
			node.setFieldName("son");
			node.setElementClass(Node.class);
			MethodInfo create = new MethodInfo();
			create.setMethod(Node.class.getMethod("createSon", String.class,String.class));
			ArrayList<String> nodeType = new ArrayList<String> (1);
			if (this instanceof Choice){
				nodeType.add("case");
			}
			else {
				nodeType.add("container");
				nodeType.add("choice");
				nodeType.add("leaf");
				nodeType.add("list");
			}
			
			Parameter[] paras = {new Parameter("nodeType",nodeType,true),new Parameter("name",true)}; 
			create.setMethodParas(paras);
			node.setCreate(create);
			mapInfo.addCompositeField(node);
		}


		return mapInfo;
	}
	@Override
	public int compare(Object data) {
		if (null == data){
			return 1;
		}
		
		ModelElement rev = (ModelElement)data;
		if (this.getName().compareTo(rev.getName()) > 0){
			return 1;
		}
		else if (this.getName().compareTo(rev.getName()) < 0){
			return -1;
		}
		else {
			if (this.getPrefix().compareTo(rev.getPrefix()) > 0){
				return 1;
			}
			else if (this.getPrefix().compareTo(rev.getPrefix()) < 0){
				return -1;
			}
		}
		return 0;

	}
//	public Element generateSchema(Namespace ns){
//		Element root = new Element(this.getName());
//		root.setNamespace(ns);
//		int size = this.getSonsNumber();
//		for(int i = 0;i < size; i++){
//			Node n = this.getSon(i);
//			if (null == n){
//				continue;
//			}
//			
//			Element ne = n.generateSchema(ns);
//			if (null != ne){
//				root.addContent(ne);
//			}
//		}
//		
//		return root;
//	}
	
	public boolean isKey(){
		boolean isKey = false;
		if(this.getParent() instanceof YangList){
			YangList parentNode = (YangList)this.getParent();
			for(int i = 0; i < parentNode.getKeyFieldsNumber(); i++){
				if(this.getName().equals(parentNode.getKeyField(i))){
					isKey = true;
					break;
				}
			}
		}
		return isKey;
	}
}
